/**
 * Copyright © 2014 TingerSure. All rights reserved.
 */
package org.sure.scomet.link;

import java.io.Serializable;

import javax.servlet.http.HttpSession;

import org.sure.scomet.action.ConnectionAction;
import org.sure.scomet.util.ConfigManager;
import org.sure.scomet.util.UnicodeTool;
import org.sure.scomet.util.log.LogManager;
import org.sure.scomet.util.log.LogType;

public class Connection implements Serializable {

	/**
	 * the serialVersion UID
	 */
	private static final long serialVersionUID = 1L;

	private static int buffer;

	public int getPageId() {
		return pageId;
	}

	public void clientMessage(String message, HttpSession session)
			throws ConnectionOutofMaxTimeException {
		ConnectionCenter.check(this);
		try {
			message = UnicodeTool.unicodeToUtf8(message);
			ConnectionCenter.getCallBack().messageCallBack(pageId, session,
					message);
		} catch (NullPointerException e) {
			LogManager.logException("no call back method", e, LogType.warn);
		}
	}

	private StringBuffer backMessage = new StringBuffer();

	public boolean write(String message)
			throws ConnectionOutofMaxTimeException, NullPointerException {
		ConnectionCenter.check(this);
		lastLink = System.currentTimeMillis();
		backMessage.append(message);
		if (backMessage.length() > buffer) {
			return this.flush();
		}
		return false;
	}

	public boolean flush() throws ConnectionOutofMaxTimeException,
			NullPointerException {
		ConnectionCenter.check(this);
		if (backMessage.length() == 0) {
			return true;
		}
		for (int i = 0; i < 60; i++) {
			if (send == null) {
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e) {
					LogManager.logException("buffer flush wrong", e,
							LogType.error);
				}
				continue;
			}
			send.setMessage(backMessage.toString());
			synchronized (send) {
				send.notify();
			}
			send = null;
			backMessage.delete(0, backMessage.length());
			lastLink = System.currentTimeMillis();
			return true;
		}
		close();
		throw new ConnectionOutofMaxTimeException("no connection here.");
	}

	protected void setPageId(int pageId) {
		this.pageId = pageId;
	}

	public void setSend(ConnectionAction send) {
		this.send = send;
	}

	public long getLastLink() {
		return lastLink;
	}

	private long lastLink = System.currentTimeMillis();

	private int pageId;

	private ConnectionAction send = null;

	public ConnectionAction getSend() {
		return send;
	}

	public static void init() {
		try {
			buffer = Integer.parseInt(ConfigManager.getConfig(
					"connection-buffer", "1000"));
			if (buffer < 1) {
				throw new NumberFormatException(Integer.toString(buffer));
			}
		} catch (NumberFormatException e) {
			LogManager
					.logException(
							"The config length of the connection string buffer is wrong! ",
							e, LogType.fatal);
		}
	}

	public void close() {
		ConnectionCenter.closeConnection(pageId);
	}

	public static void destroy() {
		buffer = 0;
	}
}
